using System;
using System.Reflection;

namespace WCSFContrib.Extensions.EventBroker
{
	/// <summary>
	/// Exception for attempting to start an application with publisher-subscriber mismatch.
	/// Also thrown when publish-subscribe hookup fails in runtime.
	/// </summary>
	public class EventHookupException : Exception
	{
		public EventHookupException(string subscribingTypeName, string subscribingMethodName,
											 string publishingEventName,
											 Exception innerException) :
			base(BuildMessageForUnableToCreateDelegate(subscribingTypeName, subscribingMethodName, publishingEventName),
				  innerException)
		{ }

		public EventHookupException(object publisher, object dataToPublish,
											 object subscriber, MethodBase methodToCall,
											 Exception innerException) :
			base(BuildMessageForBadObjectData(publisher, dataToPublish,
														 subscriber, methodToCall),
				  innerException)
		{ }

		public EventHookupException(MemberReference<EventInfo> eventReference,
											 MemberReference<MethodInfo> handlerReference,
											 Exception innerException) :
			base(BuildMessageForMemberRefMismatch(eventReference, handlerReference),
				  innerException)
		{ }

		#region Build error messages from parameters and resource messages
		private static string BuildMessageForUnableToCreateDelegate(string subscribingTypeName, string subscribingMethodName,
																						string publishingEventName)
		{
			return string.Format(Properties.Resources.UnableToCreateDelegate,
										subscribingTypeName, subscribingMethodName,
										publishingEventName);
		}

		private static string BuildMessageForBadObjectData(object publisher, object dataToPublish,
																			object subscriber, MethodBase methodToCall)
		{
			return string.Format(Properties.Resources.HookupExceptionSanityMismatch,
										subscriber,
										methodToCall.Name, methodToCall.GetParameters()[0],
										dataToPublish.GetType(), publisher);
		}

		private static string BuildMessageForMemberRefMismatch(MemberReference<EventInfo> eventReference,
																				 MemberReference<MethodInfo> handlerReference)
		{
			return string.Format(Properties.Resources.HookupRuntimeExeption,
											eventReference.Topic,
											eventReference.Info.DeclaringType.FullName, eventReference.Info.Name,
											handlerReference.Info.DeclaringType.FullName, handlerReference.Info.Name);
		}
		#endregion
	}
}